(define (make-queue)
    (let 
        (
            (front-ptr `())
            (rear-ptr `())
        )
        (define (set-front-ptr! item)
            (set! front-ptr item)
        )
        (define (set-rear-ptr! item)
            (set! rear-ptr item)
        )
        (define (empty-queue?) 
            (null? front-ptr)
        )
        
        (define (insert-queue! item)
            (let 
                ((new-pair (cons item `())))
                (cond 
                    ((empty-queue?) 
                        (set-front-ptr! new-pair)
                        (set-rear-ptr! new-pair)
                    )
                    (else
                        (set-cdr! rear-ptr new-pair)
                        (set-rear-ptr! new-pair)
                    )
                )
            )
        )

        (define (delete-queue!)
           
            (if (empty-queue?)
                (error "DELETE empty queue" queue)
                (   
                    set-front-ptr! (cdr front-ptr)
                )
            )
        )

        (define (print-queue) 
            (newline)           
            (display "queue:")
            (display front-ptr)            
        )
    
        (define (dispatch m) 
            (cond 
                ((eq? m `set-front-ptr!) set-front-ptr!)
                ((eq? m `set-rear-ptr!) set-rear-ptr!)
                ((eq? m `empty-queue?) empty-queue?)
                ((eq? m `insert-queue!) insert-queue!)
                ((eq? m `delete-queue!) delete-queue!)
                ((eq? m `print-queue) print-queue)
                (else (error "...." m))
            )    
        )
        dispatch        
    )
)


(define q1 (make-queue))
((q1 `insert-queue!) `a)
((q1 `print-queue))
((q1 `insert-queue!) `b)
((q1 `print-queue))
((q1 `delete-queue!)) 
((q1 `print-queue))
((q1 `delete-queue!)) 
((q1 `print-queue))
(exit)


